using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Web;
using CSScriptLibrary;
using log4net;

namespace MovieRenamer
{
	public class Utils
	{
		private static readonly ILog log = LogManager.GetLogger(typeof(Utils));
		
        private static Dictionary<string, IScriptGrabber> grabbers = new Dictionary<string, IScriptGrabber>();
			
        private static Dictionary<string, string> replacements = null;
        
		private static IScriptGrabber GetGrabber(string scriptFileName)
        {
            IScriptGrabber grabber = null;
            if (!grabbers.TryGetValue(scriptFileName, out grabber))
            {
                string scriptPath = string.Format(@"{0}\scripts\{1}.csscript", Application.StartupPath, scriptFileName);
                if (File.Exists(scriptPath))
                {
                    try
                    {
                    	//CSScriptLibrary.CSScript.GlobalSettings.AddSearchDir(@"c:\work\Projects.NET\MovieRenamer\MovieRenamer\bin\Debug\");
                        AsmHelper script = new AsmHelper(CSScriptLibrary.CSScript.Load(scriptPath, null, false));
                        grabber = (IScriptGrabber)script.CreateObject("Grabber");
                    }
                    catch (System.Exception ex)
                    {
                        log.Error(string.Format("Error loading grabber script: {0}, message: {1}", scriptPath, ex.Message), ex);
                    }
                }
                else
                {
                    log.Error(string.Format("Grabber script not found: {0}", scriptPath));
                }

            }
            return grabber;
        }
			
		public static void FindMatchedMovies(MovieFile movieFile)
		{
            IScriptGrabber grabber = GetGrabber("kinopoisk_ru");
            if (grabber != null)
            {
            	try
            	{
            		movieFile.MatchedMovies.Clear();
            		string searchString = HttpUtility.UrlEncode(string.IsNullOrEmpty(movieFile.SearchString) ? GetSearchString(movieFile.FileName) : movieFile.SearchString);
            		grabber.FindMovie(searchString, movieFile.MatchedMovies);
            	}
            	catch (System.Exception ex)
            	{
            		log.Error(string.Format("Error searching, message: {1}", ex.Message), ex);
                }
            }
		}
		
		public static string GetReplacement(string str)
		{
			string repl = str;
			if (replacements == null)
			{
				replacements = new Dictionary<string, string>();
				StreamReader reader = File.OpenText(Path.Combine(Application.StartupPath, "Replacements.txt"));
				string line;
				while ((line = reader.ReadLine()) != null)
				{
					string[] arr = line.Split(';');
					if (arr.Length > 0)
					{
						string key = arr[0];
						string value = string.Empty;
						if (arr.Length > 1)
						{
							value = arr[1];
						}
						
						replacements.Add(key.ToUpper(), value);
					}
				}
			}
			
			if (!string.IsNullOrEmpty(str)) {
				string value;
				if (replacements.TryGetValue(str.ToUpper(), out value))
				{
					repl = value;
				}
			}
			
			return repl;
		}
		
        private static void RemoveAllAfter(ref string line, string word)
        {
            int pos = line.IndexOf(word);
            if (pos > 0)
            {
                line = line.Substring(0, pos);
            }
        }
        
        public static string GetSearchString(string movieTitle)
        {
            string strURL = movieTitle;
            strURL = strURL.ToLower();
            strURL = strURL.Trim();

            // @ 23.09.2004 by FlipGer
            if (strURL.Length <= 7)
            {
                return strURL;
            }
            // END @ | i think it does not make much sense to parse such a short string
            // and i have no problems with x-men on OFDB ;-) and a better result on IMDB with x-men (try out "x men" :-)

            string strTmp = "";
            int ipos = 0;
            int iBracket = 0;
            //bool	bSkip = false;
            for (int i = 0; i < strURL.Length; ++i)
            {
                char kar = strURL[i];
                if (kar == '[' || kar == '(')
                    iBracket++;			//skip everthing between () and []
                else if (kar == ']' || kar == ')')
                    iBracket--;
                else if (iBracket <= 0)
                {
                    // change all non cahrs or digits into ' '
                    if (!Char.IsLetterOrDigit(kar))
                    {
                        kar = ' ';

                    }
                    // skip whitespace at the beginning, only necessary if the "number skipping" is used
                    //if ((kar==' ') && (ipos==0)) continue;

                    // Mars Warrior @ 03-sep-2004.
                    // Check for ' ' and '+' to avoid double or more ' ' and '+' which
                    // mess up the search to the IMDB...
                    if (strTmp.Length == 0)
                    {
                        strTmp += kar;
                        ipos++;
                    }
                    else
                    {
                        if (
                          Char.IsLetterOrDigit(kar) ||
                          (kar == ' ' && strTmp[strTmp.Length - 1] != ' ')
                            //|| (kar == '+' && strTmp[strTmp.Length -1] != '+')
                          )
                        {
                            strTmp += kar;
                            ipos++;
                        }
                    }
                }
            }

            strTmp = strTmp.Trim();

            // Mars Warrior @ 03-sep-2004.
            // The simple line "strTmp.ToLower()" does NOT work. As a result the wrong string
            // (still includes the " dvd" etc. strings) is send to the IMDB causing wrong lookups
            // By changing the line, everything is working MUCH better now ;-)

            RemoveAllAfter(ref strTmp, "divx");
            RemoveAllAfter(ref strTmp, "xvid");
            RemoveAllAfter(ref strTmp, "dvd");
            RemoveAllAfter(ref strTmp, "dvdrip");
            RemoveAllAfter(ref strTmp, "svcd");
            RemoveAllAfter(ref strTmp, "mvcd");
            RemoveAllAfter(ref strTmp, "vcd");
            RemoveAllAfter(ref strTmp, "cd");
            RemoveAllAfter(ref strTmp, "ac3");
            RemoveAllAfter(ref strTmp, "ogg");
            RemoveAllAfter(ref strTmp, "ogm");
            RemoveAllAfter(ref strTmp, "internal");
            RemoveAllAfter(ref strTmp, "fragment");
            RemoveAllAfter(ref strTmp, "proper");
            RemoveAllAfter(ref strTmp, "limited");
            RemoveAllAfter(ref strTmp, "rerip");
            RemoveAllAfter(ref strTmp, "bdrip");
            RemoveAllAfter(ref strTmp, "bdremux");
            RemoveAllAfter(ref strTmp, "bd-remux");
            RemoveAllAfter(ref strTmp, "hddvdrip");
            RemoveAllAfter(ref strTmp, "hddvdremux");
            RemoveAllAfter(ref strTmp, "hddvd-remux");
            RemoveAllAfter(ref strTmp, "hdtv");
            RemoveAllAfter(ref strTmp, "hdtvrip");
            RemoveAllAfter(ref strTmp, "1080p");
            RemoveAllAfter(ref strTmp, "1080i");
            RemoveAllAfter(ref strTmp, "720p");
            RemoveAllAfter(ref strTmp, "x264");
            RemoveAllAfter(ref strTmp, "h264");
            RemoveAllAfter(ref strTmp, "vc1");
            RemoveAllAfter(ref strTmp, "vc-1");
            RemoveAllAfter(ref strTmp, "dts");
            RemoveAllAfter(ref strTmp, "sub");
            RemoveAllAfter(ref strTmp, "rus");
            RemoveAllAfter(ref strTmp, "eng");

            RemoveAllAfter(ref strTmp, "+divx");
            RemoveAllAfter(ref strTmp, "+xvid");
            RemoveAllAfter(ref strTmp, "+dvd");
            RemoveAllAfter(ref strTmp, "+dvdrip");
            RemoveAllAfter(ref strTmp, "+svcd");
            RemoveAllAfter(ref strTmp, "+mvcd");
            RemoveAllAfter(ref strTmp, "+vcd");
            RemoveAllAfter(ref strTmp, "+cd");
            RemoveAllAfter(ref strTmp, "+ac3");
            RemoveAllAfter(ref strTmp, "+ogg");
            RemoveAllAfter(ref strTmp, "+ogm");
            RemoveAllAfter(ref strTmp, "+internal");
            RemoveAllAfter(ref strTmp, "+fragment");
            RemoveAllAfter(ref strTmp, "+proper");
            RemoveAllAfter(ref strTmp, "+limited");
            RemoveAllAfter(ref strTmp, "+rerip");
            RemoveAllAfter(ref strTmp, "+bdrip");
            RemoveAllAfter(ref strTmp, "+bdremux");
            RemoveAllAfter(ref strTmp, "+bd-remux");
            RemoveAllAfter(ref strTmp, "+hddvdrip");
            RemoveAllAfter(ref strTmp, "+hddvdremux");
            RemoveAllAfter(ref strTmp, "+hddvd-remux");
            RemoveAllAfter(ref strTmp, "+hdtv");
            RemoveAllAfter(ref strTmp, "+hdtvrip");
            RemoveAllAfter(ref strTmp, "+1080p");
            RemoveAllAfter(ref strTmp, "+1080i");
            RemoveAllAfter(ref strTmp, "+720p");
            RemoveAllAfter(ref strTmp, "+x264");
            RemoveAllAfter(ref strTmp, "+h264");
            RemoveAllAfter(ref strTmp, "+vc1");
            RemoveAllAfter(ref strTmp, "+vc-1");
            RemoveAllAfter(ref strTmp, "+dts");
            RemoveAllAfter(ref strTmp, "+sub");
            RemoveAllAfter(ref strTmp, "+rus");
            RemoveAllAfter(ref strTmp, "+eng");

            // return the new formatted string
            return strTmp;
        }
	}
}
